Risk Characteristics: Patterns and Features of Security Incidents

In this section, we will analyze the patterns and characteristics of security incidents faced by aid workers, focusing on attack methods, targeted organizations, and differences between local and international personnel, to better understand the nature and specific features of these incidents.

1. Attack Methods Analysis

First, let’s explore the distribution of different attack methods and their impact on aid workers.

Code
import plotly.express as px

attack_methods = df['Means of attack'].value_counts().reset_index()
attack_methods.columns = ['Attack Method', 'Count']
attack_methods = attack_methods[attack_methods['Count'] > 20]
fig = px.bar(attack_methods,
            x='Attack Method',
            y='Count',
            color='Count',
            color_continuous_scale='Reds',
            text='Count')
fig.update_layout(
    title={
        'text': 'Distribution of Attack Methods',
        'y':0.95,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top'
    },
    height=500,
    width=800,
    xaxis_title='Attack Method',
    yaxis_title='Number of Incidents',
    xaxis={'categoryorder':'total descending'},
    template='plotly_white',
    margin=dict(l=80, r=80, t=80, b=80)
)

fig.update_traces(texttemplate='%{text}', textposition='outside')
fig.show()

The chart above shows the distribution of different attack methods used against aid workers. Shooting incidents significantly outnumber other types of attacks, despite firearms typically being more regulated than weapons like knives. This can also indicate that these conflicts are very violent and probably at the level of the State and the military.

Next, let’s analyze the casualty rates for different attack methods:

Code
import plotly.graph_objects as go
attack_severity = df.groupby('Means of attack').agg({
    'Incident ID': 'count',
    'Total killed': 'sum',
    'Total wounded': 'sum',
    'Total kidnapped': 'sum'
}).reset_index()

attack_severity.columns = ['Attack Method', 'Incident Count', 'Deaths', 'Injuries', 'Kidnappings']
attack_severity['Total Affected'] = attack_severity['Deaths'] + attack_severity['Injuries'] + attack_severity['Kidnappings']
attack_severity['Fatality Rate'] = (attack_severity['Deaths'] / attack_severity['Total Affected'] * 100).round(1)
top_methods = attack_severity.sort_values('Incident Count', ascending=False).head(10)
fig = go.Figure()

fig.add_trace(
    go.Bar(
        x=top_methods['Attack Method'],
        y=top_methods['Deaths'],
        name='Deaths',
        marker_color='#d62728'
    )
)

fig.add_trace(
    go.Bar(
        x=top_methods['Attack Method'],
        y=top_methods['Injuries'],
        name='Injuries',
        marker_color='#ff7f0e'
    )
)

fig.add_trace(
    go.Bar(
        x=top_methods['Attack Method'],
        y=top_methods['Kidnappings'],
        name='Kidnappings',
        marker_color='#b58b00'
    )
)
fig.update_layout(
    title={
        'text': 'Total Casualties by Different Attack Methods',
        'y':0.97,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top'
    },
    height=500,
    width=800,
    barmode='stack',
    xaxis_title='Attack Method',
    yaxis_title='Number of Casualties',
    xaxis={'categoryorder':'total descending'},
    legend=dict(orientation="h", y=1.1, x=0.5, xanchor="center"),
    template="plotly_white",
    margin=dict(l=80, r=80, t=80, b=80)
)

fig.show()
Code
import plotly.graph_objects as go
fig = go.Figure()

fig.add_trace(
    go.Bar(
        x=top_methods['Attack Method'], 
        y=top_methods['Fatality Rate'],
        marker_color='#d62728',
        name='Fatality Rate',
        text=top_methods['Fatality Rate'].apply(lambda x: f"{x}%"),
        textposition='outside'
    )
)
fig.update_layout(
    title={
        'text': 'Fatality Rate by Attack Method (%)',
        'y':0.9,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top'
    },
    height=500,
    width=800,
    xaxis_title='Attack Method',
    yaxis_title='Fatality Rate (%)',
    xaxis={'categoryorder':'total descending'},
    template="plotly_white",
    margin=dict(l=80, r=80, t=80, b=80)
)
fig.show()

These charts reveal the disturbing impact of different attack methods. While kidnapping events are primarily focused on abduction rather than causing immediate casualties, attacks involving “kidnap-killed” (where kidnapping ends in murder), shootings, and aerial bombardment show the highest fatality rates. This indicates that when attackers intend to cause maximum harm rather than using kidnapping for ransom or political leverage, the outcomes are significantly more deadly.

2. Target Organization Analysis

Now, let’s examine which organizations are most frequently targeted and the impact on their personnel.

Code
import plotly.express as px
org_columns = ['UN', 'INGO', 'ICRC', 'NRCS and IFRC', 'NNGO', 'Other']
org_data = df[org_columns].sum().reset_index()
org_data.columns = ['Organization', 'Incident Count']
org_data = org_data.sort_values('Incident Count', ascending=False)
fig = px.pie(
    org_data,
    values='Incident Count',
    names='Organization',
    color_discrete_sequence=px.colors.qualitative.Set3
)
fig.update_layout(
    title={
        'text': 'Distribution of Attacks Across Different Organizations',
        'y':0.9,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top'
    },
    height=500,
    width=700,
    legend_title="Organization Type",
    template="plotly_white",
    margin=dict(l=80, r=80, t=80, b=80)
)

fig.update_traces(textposition='inside', textinfo='percent+label+value')
fig.show()

The pie chart shows that International Non-Governmental Organizations (INGOs), National Non-Governmental Organizations (NNGOs), and United Nations (UN) entities are the most frequently targeted organizations. INGOs are international humanitarian organizations operating across borders like Médecins Sans Frontières, Save the Children, and Oxfam. NNGOs are locally established aid organizations working within their own countries. The UN includes various agencies such as UNICEF, UNHCR, and the World Food Programme. These organizations often have the most visible presence in conflict zones, making them more vulnerable to attacks. Of course, this is also related to the number of people in these organizations; the larger the organization, the greater the number of staff members implicated on average.

Let’s analyze the casualties among different organizations:

Code
import plotly.express as px
org_casualties = pd.DataFrame()
for org in org_columns:
    temp_df = df[df[org] > 0]
    casualties = temp_df.groupby('Year')[['Total killed', 'Total wounded', 'Total kidnapped']].sum().reset_index()
    casualties['Organization'] = org
    org_casualties = pd.concat([org_casualties, casualties])

org_casualties.columns = ['Year', 'Deaths', 'Injuries', 'Kidnappings', 'Organization']
org_casualties['Total Casualties'] = org_casualties['Deaths'] + org_casualties['Injuries'] + org_casualties['Kidnappings']
fig = px.bar(
    org_casualties,
    x='Organization',
    y='Total Casualties',
    color='Organization',
    barmode='group'
)
fig.update_layout(
    title={
        'text': 'Total Casualties by Organization Type',
        'y':0.9,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top'
    },
    height=500,
    width=800,
    xaxis_title='Organization Type',
    yaxis_title='Number of Casualties',
    legend_title="Organization",
    template='plotly_white',
    margin=dict(l=80, r=80, t=80, b=80)
)
fig.show()
Code
import plotly.express as px
yearly_org_casualties = org_casualties.pivot_table(
    index='Year', 
    columns='Organization', 
    values='Total Casualties',
    aggfunc='sum'
).fillna(0)
recent_years = sorted(yearly_org_casualties.index)[-20:]
yearly_org_casualties_recent = yearly_org_casualties.loc[recent_years]
fig = px.line(
    yearly_org_casualties_recent,
    labels={'value': 'Number of Casualties', 'variable': 'Organization'}
)
fig.update_layout(
    title={
        'text': 'Yearly Casualties by Organization Type (Last 20 Years)',
        'y':0.95,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top'
    },
    height=500,
    width=800,
    xaxis_title='Year',
    yaxis_title='Number of Casualties',
    legend_title="Organization",
    hovermode="x unified",
    template='plotly_white',
    margin=dict(l=80, r=80, t=80, b=80)
)
fig.show()

The time analysis of attacks on different organizations reveals important patterns. INGOs experienced a peak in attacks in 2019, while UN agencies saw a dramatic increase in 2023. NNGOs have reached their highest point in 2024. These fluctuations likely reflect changing conflict dynamics and the varying presence of different organizations in high-risk areas. The recent surge in attacks on NNGOs might indicate that local organizations are increasingly being targeted as they take on more prominent roles in humanitarian response.

3. Local vs International Aid Worker Analysis

Finally, let’s compare the risks faced by national (local) and international aid workers.

Code
import plotly.graph_objects as go
from plotly.subplots import make_subplots
national_intl = df.groupby('Year').agg({
    'Nationals killed': 'sum',
    'Nationals wounded': 'sum',
    'Nationals kidnapped': 'sum',
    'Internationals killed': 'sum',
    'Internationals wounded': 'sum',
    'Internationals kidnapped': 'sum'
}).reset_index()

national_intl['Total National Casualties'] = national_intl['Nationals killed'] + national_intl['Nationals wounded'] + national_intl['Nationals kidnapped']
national_intl['Total International Casualties'] = national_intl['Internationals killed'] + national_intl['Internationals wounded'] + national_intl['Internationals kidnapped']
fig = make_subplots(
    rows=2, 
    cols=1,
    vertical_spacing=0.25,
    specs=[[{"type": "scatter"}], [{"type": "scatter"}]]
)
fig.layout.annotations = []
fig.add_annotation(
    text="Total Casualties: Local vs International Aid Workers",
    xref="paper",
    yref="paper",
    x=0.5,
    y=1.1,
    showarrow=False,
    font=dict(size=14)
)

fig.add_annotation(
    text="Proportion of Casualties: Local vs International",
    xref="paper",
    yref="paper",
    x=0.5,
    y=0.45,
    showarrow=False,
    font=dict(size=14)
)
fig.add_trace(
    go.Scatter(
        x=national_intl['Year'],
        y=national_intl['Total National Casualties'],
        mode='lines+markers',
        name='Local Aid Workers',
        line=dict(width=3, color='#1f77b4')
    ),
    row=1, col=1
)

fig.add_trace(
    go.Scatter(
        x=national_intl['Year'],
        y=national_intl['Total International Casualties'],
        mode='lines+markers',
        name='International Aid Workers',
        line=dict(width=3, color='#d62728')
    ),
    row=1, col=1
)
national_pct = national_intl['Total National Casualties'] / (national_intl['Total National Casualties'] + national_intl['Total International Casualties']) * 100
intl_pct = national_intl['Total International Casualties'] / (national_intl['Total National Casualties'] + national_intl['Total International Casualties']) * 100
fig.add_trace(
    go.Scatter(
        x=national_intl['Year'],
        y=national_pct,
        mode='lines+markers',
        name='Local Aid Workers (%)',
        line=dict(width=3, color='#1f77b4')
    ),
    row=2, col=1
)

fig.add_trace(
    go.Scatter(
        x=national_intl['Year'],
        y=intl_pct,
        mode='lines+markers',
        name='International Aid Workers (%)',
        line=dict(width=3, color='#d62728')
    ),
    row=2, col=1
)

fig.update_layout(
    height=700,
    width=850,
    hovermode="x unified",
    legend=dict(orientation="h", y=1.0, x=0.5, xanchor="center", yanchor="top"),
    template="plotly_white",
    margin=dict(l=80, r=150, t=80, b=80)
)

fig.update_yaxes(title_text="Number of Casualties", row=1, col=1)
fig.update_yaxes(title_text="Percentage (%)", row=2, col=1)
fig.update_xaxes(title_text="Year", row=2, col=1)

fig.show()

The analysis of local versus international aid worker casualties reveals a stark difference in risk exposure. Local aid workers consistently face significantly higher numbers of casualties compared to their international counterparts, and this disparity has been increasing over time.

The growing proportion of local aid worker casualties can be attributed to several factors. First, there’s been a global shift toward “localization” in humanitarian response, with more responsibilities being transferred to local organizations and staff. Second, international organizations often evacuate their expatriate staff during acute security crises while local staff continue operations. Third, local aid workers frequently access areas deemed too dangerous for international personnel, placing them at higher risk. Finally, international workers may receive more comprehensive security training and resources compared to their local workers.

Summary of Risk Characteristics

Through our analysis of security incidents affecting aid workers, several critical patterns have emerged:

  1. Attack Methods:
    • Shooting incidents represent the most common form of attack against aid workers, despite firearms typically being more regulated than other weapons
    • The most lethal attack methods are kidnapping-killings, shootings, and aerial bombardments, which show the highest fatality rates
    • Kidnapping incidents, while traumatic, tend to result in fewer immediate casualties as the primary goal is abduction rather than causing harm
  2. Target Organizations:
    • International NGOs (INGOs), National NGOs (NNGOs), and UN agencies are the most frequently targeted organizations
    • Different organizations face varying risk profiles, with peaks in attacks occurring at different times
    • INGOs experienced their highest casualty rates in 2019, while UN agencies saw a dramatic increase in 2023
    • NNGOs are currently facing their highest recorded level of attacks in 2024, suggesting a troubling shift toward targeting local humanitarian organizations
  3. Local vs International Aid Workers:
    • Local aid workers face disproportionately higher risks compared to their international counterparts
    • The percentage of casualties affecting local staff has been steadily increasing over time
    • This growing disparity reflects the increasing “localization” of humanitarian response, differential evacuation protocols, and unequal access to security resources
    • Local workers often maintain operations in high-risk areas after international staff have been evacuated

These findings highlight the complex and evolving nature of security risks in humanitarian settings. The increasing targeting of local aid workers and national organizations is particularly concerning and demands urgent attention. As the humanitarian sector continues to emphasize localization, equal investment must be made in security training, resources, and protocols for local staff and organizations.

The data suggests a need for tailored security approaches that consider the specific risks associated with different attack methods, organizational profiles, and staff nationalities. Additionally, the international humanitarian community should address the growing security disparity between local and international aid workers by ensuring that the localization of aid is accompanied by appropriate security measures and support.